package hbbft

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"strconv"
)

// NetworkConfig holds configuration for creating networks
type NetworkConfig struct {
	SelfID    uint64
	SelfAddr  string
	Peers     map[uint64]string // peerID -> "host:port"
}

// CreateTCPNetwork creates a TCP network with proper message handling
func CreateTCPNetwork(cfg NetworkConfig, hb *HoneyBadger) Network {
	// Create message handler that deserializes and processes messages
	onMessage := func(from uint64, data []byte) {
		// Record received message statistics
		hb.perfMetrics.RecordNetworkMessage(false, len(data))
		
		// Deserialize HBMessage
		var hbMsg HBMessage
		buf := bytes.NewReader(data)
		decoder := gob.NewDecoder(buf)
		if err := decoder.Decode(&hbMsg); err != nil {
			hb.logger.Error("Failed to deserialize network message", map[string]interface{}{
				"error": err.Error(),
			})
			return // Skip malformed messages
		}
		
		// Log received message
		if acsMsg, ok := hbMsg.Payload.(*ACSMessage); ok {
			hb.logger.LogNetworkMessage("received", acsMsg.ProposerID, len(data))
		}
		
		// Process ACS message
		if acsMsg, ok := hbMsg.Payload.(*ACSMessage); ok {
			// Use ProposerID from ACSMessage as sender ID
			if err := hb.HandleMessage(acsMsg.ProposerID, hbMsg.Epoch, acsMsg); err != nil {
				hb.logger.Error("Failed to handle ACS message", map[string]interface{}{
					"error": err.Error(),
					"epoch": hbMsg.Epoch,
					"proposer_id": acsMsg.ProposerID,
				})
			}
		}
	}
	
	return NewTCPNetwork(cfg.SelfID, cfg.SelfAddr, cfg.Peers, onMessage)
}

// ParsePeerAddresses parses peer addresses from a map of string IDs to addresses
func ParsePeerAddresses(peerAddrs map[string]string) (map[uint64]string, error) {
	peers := make(map[uint64]string)
	for idStr, addr := range peerAddrs {
		id, err := strconv.ParseUint(idStr, 10, 64)
		if err != nil {
			return nil, fmt.Errorf("invalid peer ID %s: %v", idStr, err)
		}
		peers[id] = addr
	}
	return peers, nil
}

// Example usage:
// peerAddrs := map[string]string{
//     "0": "localhost:8000",
//     "1": "localhost:8001", 
//     "2": "localhost:8002",
//     "3": "localhost:8003",
// }
// peers, _ := ParsePeerAddresses(peerAddrs)
// netCfg := NetworkConfig{
//     SelfID:   0,
//     SelfAddr: "localhost:8000",
//     Peers:    peers,
// }
// network := CreateTCPNetwork(netCfg, honeyBadger)
